#include "A_Config.h"
#define FILE_PER_PAGE 10
#define MUSIC_PLAYER_DIR "/m"
#define FILE_LIST_COUNT 200

enum : uint8_t
{
    LOOP_NONE = 0,
    LOOP_SINGLE,
    LOOP_LIST
} loopMode;
/////// LVGL 相关变量
static lv_obj_t *scr_music_player;
static lv_obj_t *window_volume = NULL;
static lv_obj_t *lst_file;
static lv_obj_t *currentButton = NULL;
static lv_obj_t *spinner_scroll;
static lv_obj_t *btn_play;
static lv_obj_t *btn_pageup;
static lv_obj_t *btn_pagedown;
// 播放进度条
static lv_obj_t *lbl_progress;
static lv_obj_t *slider_progress;

/////// 音频播放相关变量
static Audio *audio;
// char currentPlaying[100];
static volatile bool playing = false;
static volatile int volume = 0;
static volatile unsigned long currentPos;
static volatile unsigned long audioDuration;
static String currentTitle;
static String currentArtist;

////////// 文件列表相关变量
static volatile int currentPage = 0;
static volatile bool haveMore = false;
static char *fileList[FILE_LIST_COUNT];
static volatile uint16_t currentPlayingid = 0;
static volatile uint16_t musicTotal = 0;
//////// GUI事件变量
static bool refreshReq = false;
static bool pageDownReq = false;
static bool pageUpReq = false;
static bool loopModeReq = false;
static bool removeReq = false;
static bool renameReq = false;
static bool volumeChanged = false;
static bool positionChanged = false;
static bool finishedPlaying = false;
static bool reqNextPageAndPlay = false;

////////音乐解码任务相关

static QueueHandle_t audioSetQueue = NULL;
static QueueHandle_t audioGetQueue = NULL;
static TaskHandle_t *taskMP3Handle = NULL;

enum : uint8_t
{
    SET_VOLUME,
    GET_VOLUME,
    CONNECTTOHOST,
    CONNECTTOSD,
    PAUSE_RESUME,
    GET_DURATION,
    GET_POSITION,
    SET_POSITION,
    SET_OFFSET,
    STOP_AND_CLOSE,
    REINIT_I2S
};

struct audioMessage
{
    uint8_t cmd;
    const char *txt;
    uint32_t value;
    uint32_t ret;
} audioTxMessage, audioRxMessage;

////////////////////////////////////////一些必要的函数定义
static void refreshList();
static void rebuildIndex(); // 重建音乐表

class AppMusicPlayer : public AppBase
{
private:
    /* data */
public:
    AppMusicPlayer()
    {
        name = "musicplayer";
        title = "音乐播放器";
        description = "播放TF卡中m目录下的音乐文件";
        image = "\xEF\xA3\xA4";
    }
    void setup();
    void loop();
    void destruct();
};

static AppMusicPlayer app;
//////////////////////////////////////////////////////音频任务及操作/////////////////////////////////////////////////////////////////////

static void CreateQueues()
{
    audioSetQueue = xQueueCreate(10, sizeof(struct audioMessage));
    audioGetQueue = xQueueCreate(10, sizeof(struct audioMessage));
}

static void audioTask(void *parameter)
{
    if (!audioSetQueue || !audioGetQueue)
    {
        log_e("queues are not initialized");
        while (true)
        {
            ;
        } // endless loop
    }

    struct audioMessage audioRxTaskMessage;
    struct audioMessage audioTxTaskMessage;

    audio->setPinout(I2S_BCLK, I2S_LRCLK, I2S_DATA);
    audio->setVolume(volume / 12); // 0...21

    while (true)
    {
        if (xQueueReceive(audioSetQueue, &audioRxTaskMessage, 1) == pdPASS)
        {
            if (audioRxTaskMessage.cmd == SET_VOLUME)
            {
                audioTxTaskMessage.cmd = SET_VOLUME;
                audio->setVolume(audioRxTaskMessage.value);
                audioTxTaskMessage.ret = 1;
                xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
            }
            else if (audioRxTaskMessage.cmd == CONNECTTOHOST)
            {
                audioTxTaskMessage.cmd = CONNECTTOHOST;
                audioTxTaskMessage.ret = audio->connecttohost(audioRxTaskMessage.txt);
                xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
            }
            else if (audioRxTaskMessage.cmd == CONNECTTOSD)
            {
                audioTxTaskMessage.cmd = CONNECTTOSD;
                audio->stopSong(); // free memory
                audioTxTaskMessage.ret = audio->connecttoSD(audioRxTaskMessage.txt, audioRxTaskMessage.value);
                xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
            }
            else if (audioRxTaskMessage.cmd == GET_VOLUME)
            {
                audioTxTaskMessage.cmd = GET_VOLUME;
                audioTxTaskMessage.ret = audio->getVolume();
                xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
            }
            else if (audioRxTaskMessage.cmd == GET_POSITION)
            {
                audioTxTaskMessage.cmd = GET_POSITION;
                audioTxTaskMessage.ret = audio->getAudioCurrentTime();
                xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
            }
            else if (audioRxTaskMessage.cmd == SET_POSITION)
            {
                audioTxTaskMessage.cmd = SET_POSITION;
                audioTxTaskMessage.ret = audio->setAudioPlayPosition(audioRxTaskMessage.value);
                xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
            }
            else if (audioRxTaskMessage.cmd == GET_DURATION)
            {
                audioTxTaskMessage.cmd = GET_DURATION;
                audioTxTaskMessage.ret = audio->getAudioFileDuration();
                xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
            }
            else if (audioRxTaskMessage.cmd == SET_OFFSET)
            {
                audioTxTaskMessage.cmd = SET_OFFSET;
                audio->setTimeOffset(audioRxTaskMessage.value);
                audioTxTaskMessage.ret = 1;
                xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
            }
            else if (audioRxTaskMessage.cmd == PAUSE_RESUME)
            {
                audioTxTaskMessage.cmd = PAUSE_RESUME;
                audioTxTaskMessage.ret = audio->pauseResume();
                xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
            }
            else if (audioRxTaskMessage.cmd == STOP_AND_CLOSE)
            {
                audioTxTaskMessage.cmd = STOP_AND_CLOSE;
                audioTxTaskMessage.ret = audio->stopSong();
                xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
            }
            else if (audioRxTaskMessage.cmd == REINIT_I2S)
            {
                audioTxTaskMessage.cmd = REINIT_I2S;
                audio->reInit(false, I2S_CHANNEL_STEREO, AUDIO_I2S_DEVICE);
                audio->forceMono(false);
                audioTxTaskMessage.ret = true;
                xQueueSend(audioGetQueue, &audioTxTaskMessage, portMAX_DELAY);
            }
            else
            {
                log_i("error");
            }
        }
        audio->loop();
        // refresh audio track position
        int newAudioPos = audio->getAudioCurrentTime();
        if (currentPos != newAudioPos)
        {
            currentPos = newAudioPos;
            positionChanged = true;
            if (audioDuration == currentPos)
            {
                finishedPlaying = true;
            }
        }
        // refresh audio track duration
        unsigned long newAudioDuraton = audio->getAudioFileDuration();
        if (newAudioDuraton > 0 && audioDuration != newAudioDuraton)
        {
            audioDuration = audio->getAudioFileDuration();
            positionChanged = true;
        }
    }
}

static audioMessage transmitReceive(audioMessage msg)
{
    xQueueSend(audioSetQueue, &msg, portMAX_DELAY);
    if (xQueueReceive(audioGetQueue, &audioRxMessage, portMAX_DELAY) == pdPASS)
    {
        if (msg.cmd != audioRxMessage.cmd)
        {
            log_e("wrong reply from message queue");
        }
    }
    return audioRxMessage;
}

static void audioSetVolume(uint8_t vol)
{
    audioTxMessage.cmd = SET_VOLUME;
    audioTxMessage.value = vol;
    transmitReceive(audioTxMessage);
}

static uint8_t audioGetVolume()
{
    audioTxMessage.cmd = GET_VOLUME;
    audioMessage RX = transmitReceive(audioTxMessage);
    return RX.ret;
}

static bool audioPauseResume()
{
    audioTxMessage.cmd = PAUSE_RESUME;
    audioMessage RX = transmitReceive(audioTxMessage);
    return RX.ret;
}

static uint32_t audioStop()
{
    audioTxMessage.cmd = STOP_AND_CLOSE;
    audioMessage RX = transmitReceive(audioTxMessage);
    return RX.ret;
}

static bool audioConnecttohost(const char *host)
{
    audioTxMessage.cmd = CONNECTTOHOST;
    audioTxMessage.txt = host;
    audioMessage RX = transmitReceive(audioTxMessage);
    return RX.ret;
}

static bool audioConnecttoSD(const char *filename, unsigned long resumePos)
{
    audioTxMessage.cmd = CONNECTTOSD;
    audioTxMessage.txt = filename;
    audioTxMessage.value = resumePos;
    audioMessage RX = transmitReceive(audioTxMessage);
    return RX.ret;
}

static uint32_t audioGetPosition()
{
    audioTxMessage.cmd = GET_POSITION;
    audioMessage RX = transmitReceive(audioTxMessage);
    return RX.ret;
}

static uint32_t audioSetPosition(unsigned int secPosition)
{
    audioTxMessage.cmd = SET_POSITION;
    audioTxMessage.value = secPosition;
    audioMessage RX = transmitReceive(audioTxMessage);
    return RX.ret;
}

static uint32_t audioGetDuration()
{
    audioTxMessage.cmd = GET_DURATION;
    audioMessage RX = transmitReceive(audioTxMessage);
    return RX.ret;
}

static bool audioSetOffset(int secOffset)
{
    audioTxMessage.cmd = SET_OFFSET;
    audioTxMessage.value = secOffset;
    audioMessage RX = transmitReceive(audioTxMessage);
    return RX.ret;
}

void audio_info(const char *info)
{
    // Serial.print("info        ");
    // Serial.println(info);
    // Display the file name if id3 data is unavailable
    String infoString = (String)info;
    if (infoString.indexOf("file has no mp3") == 0)
    {
        currentTitle = String(fileList[currentPlayingid]);
        currentArtist = "";
    }
}

void audio_id3data(const char *info)
{ // id3 metadata
    // Serial.print("id3data     ");
    // Serial.println(info);

    String id3String = (String)info;
    if (id3String.indexOf("Title:") == 0)
    {
        currentTitle = id3String.substring(7);
    }
    else if (id3String.indexOf("Artist:") == 0)
    {
        currentArtist = id3String.substring(8);
    }
}
// end of mp3 file
void audio_eof_mp3(const char *)
{
    Serial.println("Music EOF.");
    // finishedPlaying = true;
}

// 打开文件
static void openFile()
{
    audioConnecttoSD(fileList[currentPlayingid], 0);
}
// 关闭文件指针
static inline void closeFile()
{
    audioStop();
}
// 修改输出方式
static void outputWayChanged()
{
    audioTxMessage.cmd = REINIT_I2S;
    transmitReceive(audioTxMessage);
    audioPauseResume();
}
///////////////////////////////////////////////////////GUI 事件/////////////////////////////////////////////////////////////////////
static void obj_volume_cb(lv_event_t *e)
{
    auto code = lv_event_get_code(e);
    if (code == LV_EVENT_VALUE_CHANGED)
    {
        volume = lv_slider_get_value(lv_event_get_target(e));
        volumeChanged = true;
    }
    else if (code == LV_EVENT_DEFOCUSED || code == LV_EVENT_LEAVE)
    {
        lv_obj_t *par = lv_event_get_target(e)->parent;
        lv_obj_fall_down(par, 24, 250, 0);
        lv_obj_del_delayed(par, 280);
    }
}

static void btn_volume_cb(lv_event_t *e)
{
    if (lv_obj_is_valid(window_volume) == false)
    {
        window_volume = lv_obj_create(app.scr);
        lv_obj_set_size(window_volume, 50, 175);
        lv_obj_align_to(window_volume, e->target, LV_ALIGN_OUT_LEFT_TOP, 30, 35);
        lv_obj_t *sld_vol = lv_slider_create(window_volume);
        lv_slider_set_value(sld_vol, volume, LV_ANIM_OFF);
        lv_obj_set_size(sld_vol, 12, lv_pct(75));
        lv_obj_align(sld_vol, LV_ALIGN_TOP_MID, 0, 0);
        lv_slider_set_range(sld_vol, 0, 127);
        lv_obj_add_event_cb(sld_vol, obj_volume_cb, LV_EVENT_ALL, NULL);

        lv_obj_t *lbl_volume = lv_label_create(window_volume);
        lv_label_set_text(lbl_volume, LV_SYMBOL_VOLUME_MAX);
        lv_obj_align(lbl_volume, LV_ALIGN_BOTTOM_MID, 0, 0);
        lv_obj_pop_up(window_volume, 24, 250, 0);
    }
    else
    {
        lv_obj_fall_down(window_volume, 24, 250, 0);
        lv_obj_del_delayed(window_volume, 280);
    }
}

void btn_play_cb(lv_event_t *e)
{
    if (currentButton == NULL)
    {
        uint32_t total = lv_obj_get_child_cnt(lst_file);
        if (total == 1)
            return;
        playing = true;
        lv_event_send(lv_obj_get_child(lst_file, 1), LV_EVENT_CLICKED, NULL);
        playing = false; // 恢复初始状态以便播放
    }
    if (playing == false)
    {
        playing = true;
        lv_label_set_text(lv_obj_get_child(btn_play, 0), LV_SYMBOL_PAUSE);
        if (audio->isRunning() == false)
            audioPauseResume();
    }
    else
    {
        playing = false;
        lv_label_set_text(lv_obj_get_child(btn_play, 0), LV_SYMBOL_PLAY);
        if (audio->isRunning() == true)
            audioPauseResume();
    }
}

void btn_prev_cb(lv_event_t *e)
{
    if (currentButton == NULL)
        return;
    int32_t id = lv_obj_get_index(currentButton);
    if (id == 1)
        return;
    auto buf = lv_obj_get_child(currentButton->parent, id - 1);
    if (buf)
    {
        lv_event_send(buf, LV_EVENT_CLICKED, NULL);
    }
}

void btn_next_cb(lv_event_t *e)
{
    if (currentButton == NULL)
        return;
    int32_t id = lv_obj_get_index(currentButton);
    auto buf = lv_obj_get_child(lst_file, id + 1);
    if (buf)
    {
        lv_event_send(buf, LV_EVENT_CLICKED, NULL);
    }
    else
    {
        reqNextPageAndPlay = true;
    }
}

static void list_cb(lv_event_t *e)
{
    lv_event_code_t code = lv_event_get_code(e);
    // 判断是否按下了列表项
    lv_obj_t *obj = lv_event_get_target(e);
    lv_obj_t *parent = lv_obj_get_parent(obj);
    lv_obj_t *cont = lv_event_get_current_target(e);
    static bool scrollOver = false;
    static int lastScroll = 0;
    if (code == LV_EVENT_CLICKED)
    {
        if (obj == cont) // 如果是点击了列表空白处，直接返回
            return;
        if (currentButton != obj)
        {
            currentButton = obj;
            currentPlayingid = lv_obj_get_child_id(obj) - 1 + (currentPage * FILE_PER_PAGE);
            openFile(); // 打开文件
            if (playing == false)
            {
                btn_play_cb(NULL); // 如果还没开始播放，模拟点击按钮
            }
        }
        currentButton = obj;
        lv_obj_scroll_to_view(obj, LV_ANIM_ON);
        uint32_t i;
        uint32_t total = lv_obj_get_child_cnt(parent);
        for (i = 1; i < total; i++)
        {
            lv_obj_t *child = lv_obj_get_child(parent, i);
            if (child == currentButton)
            {
                lv_obj_t *child1 = lv_obj_get_child(child, 0);
                lv_img_set_src(child1, LV_SYMBOL_PLAY);
            }
            else
            {
                lv_obj_t *child1 = lv_obj_get_child(child, 0);
                lv_img_set_src(child1, LV_SYMBOL_AUDIO);
            }
        }
    }
    else if (code == LV_EVENT_SCROLL) // 下拉刷新模块
    {
        int scrollNow = lv_obj_get_scroll_top(obj);
        if (lastScroll > scrollNow) // 下拉
        {
            lastScroll = scrollNow;
            lv_obj_set_y(spinner_scroll, -30 - scrollNow);
            if (scrollNow < -40)
            {
                scrollOver = true;
            }
        }
        else
        {
            lv_obj_set_y(spinner_scroll, -30 - scrollNow);
            if ((lastScroll < -40) && (scrollOver == true))
            {
                scrollOver = false;
                lv_obj_scroll_by(obj, 0, 40 + lastScroll, LV_ANIM_ON);
                refreshReq = true;
            }
            lastScroll = scrollNow;
        }
    }
}
/////////////////////////////////////////////////GUI 控制与修改/////////////////////////////////////////////////////////////////////////////
void addToList(const char *name) // 添加音乐到列表
{
    lv_obj_t *btn;
    btn = lv_list_add_btn(lst_file, LV_SYMBOL_AUDIO, name);
    lv_obj_add_flag(btn, LV_OBJ_FLAG_EVENT_BUBBLE);
    lv_obj_set_style_text_font(lv_obj_get_child(btn, 1), &lv_font_chinese_16, 0);
}

static void removeFromList() // 从列表中删除当前音乐
{
    if (currentButton == NULL)
        return;
    if (playing)
    {
        btn_play_cb(NULL);
    }
    closeFile();
    currentButton = NULL;
    delay(50);
    SDCARD.remove(fileList[currentPlayingid]);
    rebuildIndex();
    refreshList();
}

static void create_lst_file()
{
    lst_file = lv_list_create(app.scr);
    spinner_scroll = lv_spinner_create(lst_file, 1000, 100);
    lv_obj_set_style_arc_width(spinner_scroll, 4, 0);
    lv_obj_set_style_arc_width(spinner_scroll, 4, LV_PART_INDICATOR);
    lv_obj_add_flag(spinner_scroll, LV_OBJ_FLAG_FLOATING | LV_OBJ_FLAG_IGNORE_LAYOUT);
    lv_obj_align(spinner_scroll, LV_ALIGN_TOP_MID, 0, -30);
    lv_obj_set_size(spinner_scroll, 30, 30);
    lv_obj_set_size(lst_file, 200, 240 - 50);
    lv_obj_set_pos(lst_file, 10, 40);
    lv_obj_add_event_cb(lst_file, list_cb, LV_EVENT_ALL, NULL);
}

static void refreshList()
{
    int fileCountExpected = currentPage * FILE_PER_PAGE;
    uint32_t i;
    // 删除原菜单内容
    if (currentPage == 0)
    {
        lv_obj_add_state(btn_pageup, LV_STATE_DISABLED);
    }
    else
    {
        lv_obj_clear_state(btn_pageup, LV_STATE_DISABLED);
    }
    LOCKLV();
    currentButton = NULL;
    lv_obj_del(lst_file);
    create_lst_file();
    UNLOCKLV();
    uint16_t to = fileCountExpected + FILE_PER_PAGE;
    if (to > musicTotal)
        to = musicTotal;
    for (uint16_t i = fileCountExpected; i < to; ++i)
    {
        LOCKLV();
        if (fileList[i] == NULL)
            break; // 双重保险
        addToList((fileList[i]) + 3);
        UNLOCKLV();
    }
    if (to < musicTotal)
    {
        lv_obj_clear_state(btn_pagedown, LV_STATE_DISABLED);
        haveMore = true;
    }
    else
    {
        lv_obj_add_state(btn_pagedown, LV_STATE_DISABLED);
        haveMore = false;
    }
    lv_obj_scroll_to(lst_file, 0, 0, LV_ANIM_ON);
}

static void rebuildIndex() // 重建音乐表
{
    uint16_t i = 0;
    for (i = 0; i < musicTotal; ++i)
    {
        if (fileList[i] == NULL)
            break;
        free(fileList[i]);
        fileList[i] = NULL;
    }
    File root = SDCARD.open(MUSIC_PLAYER_DIR);
    if (!root)
    {
        if (SDCARD.mkdir(MUSIC_PLAYER_DIR) == false)
        {
            msgbox(LV_SYMBOL_WARNING " 错误", "无法读取音乐目录");
            lv_obj_scroll_to(lst_file, 0, 0, LV_ANIM_ON);
            return;
        }
        else
        {
            root = SDCARD.open(MUSIC_PLAYER_DIR);
        }
    }
    File file = root.openNextFile();
    musicTotal = 0;
    while (file)
    {
        if (!file.isDirectory())
        {
            size_t fn_size = strlen(file.path());
            fileList[musicTotal] = (char *)ps_malloc(fn_size + 1);
            strcpy(fileList[musicTotal], file.path());
            ++musicTotal;
        }
        file.close();
        file = root.openNextFile();
    }
    root.close();
}

static void slider_music_event_cb(lv_event_t *e)
{
    int code = lv_event_get_code(e);
    lv_obj_t *slider = lv_event_get_target(e);
    if (code == LV_EVENT_VALUE_CHANGED)
    {
        char buf[8];
        int pos = lv_slider_get_value(slider);
        lv_snprintf(buf, sizeof(buf), "%02d:%02d", pos / 60, pos % 60);
        lv_label_set_text(lbl_progress, buf);
    }
    else if (code == LV_EVENT_RELEASED)
    {
        audioSetPosition(lv_slider_get_value(slider));
    }
}

static void update_slider_pos()
{
    if (lv_slider_is_dragged(slider_progress))
        return;
    lv_slider_set_range(slider_progress, 0, audioDuration == 0 ? 1 : audioDuration);
    lv_slider_set_value(slider_progress, currentPos, LV_ANIM_OFF);
    lv_event_send(slider_progress, LV_EVENT_VALUE_CHANGED, NULL);
}
void AppMusicPlayer::setup()
{

    if (SDCARD.cardSize() == 0)
    {
        lv_toast("请先插入TF卡");
        delay(1000);
        appManager.goBack();
        return;
    }
    WiFi.disconnect(true);
    CreateQueues();
    volume = settings.getInt("settings.volume", 0);

    LOCKLV();
    lbl_progress = lv_label_create(scr);
    lv_label_set_text(lbl_progress, "--:--");
    lv_obj_set_pos(lbl_progress, 10, 15);
    slider_progress = lv_slider_create(scr);
    lv_obj_set_pos(slider_progress, 60, 15);
    lv_obj_set_width(slider_progress, 70);
    lv_obj_add_event_cb(slider_progress, slider_music_event_cb, LV_EVENT_ALL, NULL);
    lv_obj_t *btn_prev = button(scr, LV_SYMBOL_PREV, 0, 0, btn_prev_cb);
    lv_obj_set_size(btn_prev, 30, 30);
    lv_obj_align_to(btn_prev, slider_progress, LV_ALIGN_OUT_RIGHT_MID, 15, 0);
    btn_play = button(scr, LV_SYMBOL_PLAY, 0, 0, btn_play_cb);
    lv_obj_set_size(btn_play, 30, 30);
    lv_obj_align_to(btn_play, btn_prev, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
    lv_obj_t *btn_next = button(scr, LV_SYMBOL_NEXT, 0, 0, btn_next_cb);
    lv_obj_set_size(btn_next, 30, 30);
    lv_obj_align_to(btn_next, btn_play, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
    lv_obj_t *btn_audio = button(scr, LV_SYMBOL_AUDIO, 0, 0, &loopModeReq);
    lv_obj_set_size(btn_audio, 30, 30);
    lv_obj_align_to(btn_audio, btn_next, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
    lv_obj_t *btn_volume = button(scr, LV_SYMBOL_VOLUME_MAX, 0, 0, btn_volume_cb);
    lv_obj_set_size(btn_volume, 30, 30);
    lv_obj_align_to(btn_volume, btn_audio, LV_ALIGN_OUT_RIGHT_MID, 5, 0);

    create_lst_file();
    btn_pageup = button(scr, LV_SYMBOL_UP " 上一页", 0, 0, &pageUpReq);
    lv_obj_add_state(btn_pageup, LV_STATE_DISABLED);
    lv_obj_align_to(btn_pageup, lst_file, LV_ALIGN_OUT_RIGHT_TOP, 10, 0);
    btn_pagedown = button(scr, LV_SYMBOL_DOWN " 下一页", 0, 0, &pageDownReq);
    lv_obj_align_to(btn_pagedown, lst_file, LV_ALIGN_OUT_RIGHT_TOP, 10, 40);
    lv_obj_t *btn_rename = button(scr, LV_SYMBOL_EDIT " 重命名", 0, 0, &renameReq);
    lv_obj_align_to(btn_rename, lst_file, LV_ALIGN_OUT_RIGHT_TOP, 10, 80);
    lv_obj_t *btn_delete = button(scr, LV_SYMBOL_TRASH " 删除", 0, 0, &removeReq);
    lv_obj_align_to(btn_delete, lst_file, LV_ALIGN_OUT_RIGHT_TOP, 10, 120);
    UNLOCKLV();

    hal.axpShortPress = false;
    hal.DoNotSleep = true;
    loopMode = LOOP_LIST;
    audio = new Audio(false, I2S_CHANNEL_STEREO, AUDIO_I2S_DEVICE);
    audio->forceMono(false);
    /////////////////////////////////////////////////////下面开始初始化输入输出
    rebuildIndex();
    refreshList();
    xTaskCreatePinnedToCore(
        audioTask,             /* Function to implement the task */
        "audioplay",           /* Name of the task */
        5000,                  /* Stack size in words */
        NULL,                  /* Task input parameter */
        5 | portPRIVILEGE_BIT, /* Priority of the task */
        taskMP3Handle,         /* Task handle. */
        0                      /* Core where the task should run */
    );
    audioSetVolume(volume / 12);
}

void AppMusicPlayer::loop()
{

    if (hal.axpShortPress)
    {
        hal.axpShortPress = false;
        appManager.goBack();
        return;
    }
    if (refreshReq)
    {
        refreshReq = false;
        rebuildIndex();
        refreshList();
    }
    if (pageDownReq)
    {
        ++currentPage;
        refreshList();
        pageDownReq = false;
    }
    if (pageUpReq)
    {
        --currentPage;
        refreshList();
        pageUpReq = false;
    }
    if (removeReq)
    {
        if (msgbox_yn("是否删除选择的歌曲"))
        {
            removeFromList();
        }
        removeReq = false;
    }
    if (renameReq)
    {
        String renameTo = msgbox_string("请输入文件名", false, false, true);
        if (renameTo != "")
        {
            renameTo = String(MUSIC_PLAYER_DIR "/") + renameTo + ".mp3";
            if (playing)
            {
                btn_play_cb(NULL);
            }
            closeFile();
            delay(50);
            SDCARD.rename(fileList[currentPlayingid], renameTo.c_str());
            strcpy(fileList[currentPlayingid], renameTo.c_str());
            openFile();
        }
        renameReq = false;
    }
    if (volumeChanged)
    {
        volumeChanged = false;
        // TODO:改进音量控制
        audioSetVolume(volume / 12);
    }
    if (positionChanged == true)
    {
        positionChanged = false;
        update_slider_pos();
    }
    if (finishedPlaying)
    {
        btn_play_cb(NULL);
        switch (loopMode)
        {
        case LOOP_NONE:
            break;
        case LOOP_SINGLE:
            if (currentButton == NULL)
                break;
            lv_event_send(currentButton, LV_EVENT_CLICKED, NULL);
            break;
        case LOOP_LIST:
            btn_next_cb(NULL);
            break;
        default:
            break;
        }
        finishedPlaying = false;
    }
    if (loopModeReq)
    {
        menu_create();
        menu_add(LV_SYMBOL_PAUSE " 播完暂停");
        menu_add(LV_SYMBOL_LOOP " 单曲循环");
        menu_add(LV_SYMBOL_LIST " 列表循环");
        menu_add(LV_SYMBOL_REFRESH " 重载音频驱动");
        switch (menu_show())
        {
        case 1:
            loopMode = LOOP_NONE;
            break;
        case 2:
            loopMode = LOOP_SINGLE;
            break;
        case 3:
            loopMode = LOOP_LIST;
            break;
        case 4:
            outputWayChanged();
        default:
            break;
        }
        loopModeReq = false;
    }
    if (reqNextPageAndPlay)
    {
        lv_obj_t *buf;
        if (haveMore == true) // 如果还有下一页
        {
            ++currentPage;
        }
        else
        {
            currentPage = 0;
        }
        refreshList();
        delay(20);
        buf = lv_obj_get_child(lst_file, 1);
        currentButton = NULL;
        if (lv_obj_is_valid(buf))
        {
            lv_event_send(buf, LV_EVENT_CLICKED, NULL);
        }
        reqNextPageAndPlay = false;
    }
}

void AppMusicPlayer::destruct()
{
    WiFi.mode(WIFI_OFF);
    ESP.restart();
}
